﻿/*  
 *  IIS LogFile Analyser, Copyright (C) 2013. http://www.iis-analyser.com
 *  --
 *  This program is free software, provided "AS IS" WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
 * 
 *  File Author: Ian Quigley,    2013-02-23
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Text;

namespace Web.Filter
{
    public class FilterFactory
    {
        private static Dictionary<string, Type> _types;

        private static Dictionary<string, Type> FindTypes()
        {
            var types = new Dictionary<string, Type>();

            var asm = Assembly.GetExecutingAssembly();
            foreach (var type in asm.GetTypes().Where( t => t.GetInterface( "IFilterView" ) != null ))
            {
                var view = (IFilterView)Activator.CreateInstance( type );
                types.Add( view.Name, type );
            }

            return types;
        }

        public static Dictionary<string, Type> Types
        {
            get
            {
                return _types ?? (_types = FindTypes());
            }

        }
        public static List<string> Names
        {
            get
            {
                return Types.Select( t => t.Key ).ToList();
            }
        }

        public static IFilterView Create( string typeName)
        {
            var filterType = Types.Single( t => t.Value.Name == typeName );
            return (IFilterView)Activator.CreateInstance( filterType.Value );
        }

        internal static string BuildHtmlFor( string filters )
        {
            StringBuilder html = new StringBuilder();
            var filterList = filters.Split( ' ' ).Where( str => !string.IsNullOrWhiteSpace( str ) );

            if (filterList.Any())
                html.Append( "<table cellspacing='0' style='margin-bottom:10px; width:500px;'><thead><tr><td colspan=2>Filters</td></tr></thead>" );

            foreach (var filterCode in filterList )
            {
                string filterName, filterParam;
                if (filterCode.IndexOf( '(' ) != -1 && filterCode.IndexOf(')') != -1)
                {
                    filterName = filterCode.Substring( 0, filterCode.IndexOf( '(' ) );
                    filterParam = filterCode.Substring( filterCode.IndexOf( '(' ) + 1, filterCode.IndexOf( ')' ) - filterCode.IndexOf( '(' ) - 1 );

                    var filter = Create( filterName );
                    if (filter != null)
                    {
                        html.Append( "<tr>" );
                        filter.BuildHtml( html, filterParam );
                        html.Append( "</tr>" );
                    }
                }
            }

            if (filterList.Any())
                html.Append( "</table>" );
            

            return html.ToString();
        }

        internal static string UpdateSql( List<FilterItem> filters, string sql )
        {
            if (filters != null && filters.Any())
            {
                foreach (var item in filters)
                {
                    var filter = Create( item.TypeName );
                    if (filter != null)
                        sql = filter.UpdateSql( sql, item );
                }
            }

            int where = sql.IndexOf( "where", StringComparison.OrdinalIgnoreCase );
            if (where != -1)
            {
                int open = sql.IndexOf('{', where);
                int close = sql.IndexOf( '}', where );

                while (open != -1 && close != -1)
                {
                    close++;
                    sql = sql.Substring( 0, open ) + "(1=1) " + sql.Substring( close );

                    open = sql.IndexOf( '{', close );
                    close = sql.IndexOf( '}', close);
                }
            }

            return sql;
        }

    }
}